<?php
namespace JaPhIM;

use JaPhIM\lib\cache\FileCache;
use JaPhIM\lib\db\DbPool;
use JaPhIM\lib\handle\OnMessage;
use JaPhIM\lib\core\Core;
use JaPhIM\lib\log\Log;
use JaPhIM\lib\log\LogHandler;
use Swoole\Process;
use Swoole\WebSocket\Server as SwooleServer;

class Server extends SwooleServer
{
    use OnMessage;

    protected $core;

    protected $log;

    protected $config;

    protected $db;

    protected $cahce;

    protected $process;

    public function __construct(Process $process = null)
    {
        $this->process = $process;
        $this->config = require_once __DIR__.'/../config.php';
        parent::__construct($this->config['server']['host'], $this->config['server']['port']);
        $this->set($this->config['swoole_server']);
        $logHandle = new LogHandler();
        $this->log = Log::Init($logHandle,15);
        $this->cahce = new FileCache();
        $this->run();
    }

    public function onWorkerStart($server, $workerId)
    {
        $this->db = new DbPool(50);
        $this->core = new Core($this->db);
    }

    protected function onOpen($server, $request)
    {

    }

    protected function onMessage($server,  $frame)
    {
        $msg = json_decode($frame->data,true);

        if (empty($msg['type'])){
            $this->sendJson($frame->fd,'未定义指令');
        }else{
            $func = strtolower($msg['type']);
            if (method_exists($this, $func)){
                $this->$func($server,  $frame->fd, $msg);
            }else{
                $this->sendJson($frame->fd,'未定义的指令方法'.$func);
            }
        }
    }

    protected function onClose($server, $fd)
    {
        //主动关闭，已由心跳检测替换
//        $this->core->offline($this->getUserId($fd));
//        $this->broadcast([
//            'type' => 'offline',
//            'user_id' => $this->getUserId($fd),
//        ]);
    }

    protected function onTask($data)
    {

    }

    protected function onFinish($server, $task_id, $data)
    {

    }

    protected function sendJson($client_id,$msg)
    {
        $msg = json_encode($msg);
        if (is_array($client_id)){
            foreach ($client_id as $v){
                $this->push($v,$msg);
            }
        }else{
            $this->push($client_id,$msg);
        }
    }

    protected function broadcast($msg)
    {
        $start_fd = 0;
        while(true)
        {
            $conn_list = $this->getClientList($start_fd, 10);
            if($conn_list === false)
            {
                break;
            }
            $start_fd = end($conn_list);
            foreach($conn_list as $fd)
            {
                $this->sendJson($fd, $msg);
            }
        }
    }

    private function getUserId($fd)
    {
        return $this->getClientInfo($fd)['uid'];
    }

    protected function run()
    {

        $this->on('WorkerStart',function ($server, $worker_id){
            $this->onWorkerStart($server, $worker_id);
        });

        $this->on('open',function ($server, $request){
            $this->onOpen($server,$request);
        });

        $this->on('message',function ($server, $frame){
            $this->onMessage($server,$frame);
        });

        $this->on('close',function ($server, $fd){
            $this->onClose($server, $fd);
        });

        $this->on('task',function ($server, $task_id, $from_id, $data){
            $this->onTask($data);
        });

        $this->on('finish',function ($server, $task_id, $data){
           $this->onFinish($data);
        });

    }

}